class SomeClass
end

class Module
  def attribute(params='a', &block)
    name, default = process_args(params)
    ivar = "@#{name}"
    assigned = ivar + "_assigned"

    # getters
    define_method name do
      default = instance_eval &block if block # set default to block

      unless instance_variable_get(assigned).nil?
        instance_variable_get(ivar)
      else
        default
      end
    end

    # predicates
    define_method(name + "?") { !send(name).nil? }

    # setters
    define_method name + "=" do |value|
      instance_variable_set ivar, value
      instance_variable_set assigned, true
    end
  end

  private

  def process_args(params)
    name = nil
    default = nil
    if params.is_a?(Hash)
      name = params.keys[0]
      default = params[name]
    else
      name = params
    end

    [name, default]
  end
end
